home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / telecomm / sticpsrc.lzh / SOURCE.ARC / SCC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-08-15  |  52.2 KB  |  1,797 lines

  1. /*
  2.  * Generic driver for Z8530 SCC chip in SLIP, KISS or AX.25 mode.
  3.  *
  4.  * Written by R.E. Janssen (PE1CHL) using material from earlier
  5.  * EAGLE and PC100 drivers in this package.
  6.  *
  7.  * The driver has initially been written for my own Atari SCC interface
  8.  * board, but it could eventually replace the other SCC drivers.
  9.  *
  10.  * Unfortunately, there is little consistency between the different interface
  11.  * boards, as to the use of a clock source, the solution for the fullduplex
  12.  * clocking problem, and most important of all: the generation of the INTACK
  13.  * signal.  Most designs do not even support the generation of an INTACK and
  14.  * the read of the interrupt vector provided by the chip.
  15.  * This results in lots of configuration parameters, and a fuzzy
  16.  * polltable to be able to support multiple chips connected at one interrupt
  17.  * line...
  18.  *
  19.  * when the constant SCC_HWTIMER is defined during compilation of SCC.C,
  20.  * we'll install the timer directly on the timer hardware interrupt, not on the
  21.  * timer-tick user-exit (int 1c) because some programs take over that one
  22.  * without saving and calling the original handler installed there...
  23.  *
  24.  */
  25.  
  26. #define SCC_HWTIMER            /* timer tick on hardware interrupt */
  27.  
  28. #ifdef ATARI_ST
  29. # ifdef MWC
  30. #  include <osbind.h>
  31. # endif
  32. # ifdef __TURBOC__
  33. #  include <tos.h>
  34. # endif
  35. #endif
  36.  
  37. #include <stdio.h>
  38. #include <ctype.h>
  39. #include <time.h>
  40. #include "global.h"
  41. #include "mbuf.h"
  42. #include "buffers.h"
  43. #include "iface.h"
  44. #include "slip.h"
  45. #include "scc.h"
  46. #include "8530.h"
  47. #include "8536.h"
  48. #include "ax25.h"
  49. #include "trace.h"
  50.  
  51. /* variables used by the SCC interrupt handler in sccvec.s */
  52.  
  53. #ifdef ATARI_ST
  54. ioaddr sccgpiploc;            /* location of MFP GPIP register */
  55. int    sccgpipbit;            /* bit# to test in MFP GPIP reg */
  56. ioaddr sccisrloc;            /* location of MFP ISR */
  57. int    sccisrbit;            /* bit# to clear in MFP ISR */
  58. extern void (*sccotvec)();        /* location to store old int vec */
  59.  
  60. struct sccinfo sccinfo;            /* global info about SCCs */
  61. struct sccchan *sccchan[2 * MAXSCC];    /* information per channel */
  62. ioaddr sccvecloc;            /* location to access for SCC vector */
  63. unsigned char sccmaxvec;        /* maximum legal vector from SCC */
  64. ioaddr sccpolltab[MAXSCC+1][2];        /* polling table when no vectoring */
  65. #endif
  66.  
  67. #ifdef MSDOS
  68. static void (*orgivec)();        /* original interrupt vector */
  69. extern void (*far sccotvec)();        /* location to store old int vec */
  70.  
  71. struct sccinfo sccinfo = {0};        /* global info about SCCs */
  72. struct sccchan *sccchan[2 * MAXSCC] = {0}; /* information per channel */
  73. ioaddr sccvecloc = {0};            /* location to access for SCC vector */
  74. unsigned char sccmaxvec = {0};        /* maximum legal vector from SCC */
  75. ioaddr sccpolltab[MAXSCC+1][2] = {0};    /* polling table when no vectoring */
  76.  
  77. # if ((defined(MSC) && defined(INLINE)) || (defined(__TURBOC__) && defined(inportb)))
  78. static unsigned scc_delay (v)        /* delay for about 5 PCLK cycles */
  79.    unsigned v;                /* pass-through used for input */
  80.  
  81. {
  82.    return v;                /* return the passed parameter */
  83. }
  84. # endif
  85. #endif
  86.  
  87. unsigned char random = 0;        /* random number for p-persist */
  88.  
  89. extern char nospace[];
  90.  
  91. static int scc_stop(),scc_raw(),scc_slipraw(),doscc();
  92. static void scc_async(),scc_sdlc(),scc_recv();
  93. static void scc_tossb(),scc_txon(),scc_txoff();
  94. static int scc_ax25(),scc_aioctl(),scc_sioctl();
  95. static unsigned int scc_speed();
  96.  
  97. /* Attach an SCC channel to the system, or initialize SCC driver.
  98.  * operation depends on argv[2]:
  99.  * when "init", the SCC driver is initialized, and global information about
  100.  * the hardware is set up.
  101.  * argv[0]: hardware type, must be "scc"
  102.  * argv[1]: number of SCC chips we will support
  103.  * argv[2]: mode, must be: "init" in this case
  104.  * argv[3]: base address of SCC chip #0 (hex)
  105.  * argv[4]: spacing between SCC chip base addresses
  106.  * argv[5]: offset from chip base address to channel A control register
  107.  * argv[6]: offset from chip base address to channel B control register
  108.  * argv[7]: offset from each channel's control register to data register
  109.  * argv[8]: address of INTACK/Read Vector port. 0 to read from RR3A/RR2B
  110.  * argv[9]: CPU interrupt vector number for all connected SCCs
  111.  * argv[10]: clock frequency (PCLK/RTxC) of all SCCs in cycles per second
  112.  *         prefix with "p" for PCLK, "r" for RTxC clock (for baudrate gen)
  113.  * argv[11]: optional hardware type (for special features)
  114.  * argv[12]: optional extra parameter for special hardware
  115.  *
  116.  * otherwise, a single channel is attached using the specified parameters:
  117.  * argv[0]: hardware type, must be "scc"
  118.  * argv[1]: SCC channel number to attach, 0/1 for first chip A/B, 2/3 for 2nd...
  119.  * argv[2]: mode, can be:
  120.  *        "slip", "kiss", "ax25"
  121.  * argv[3]: interface label, e.g., "sl0"
  122.  * argv[4]: maximum transmission unit, bytes
  123.  * argv[5]: interface speed, e.g, "1200". prefix with "d" when an external
  124.  *        divider is available to generate the TX clock.  When the clock
  125.  *        source is PCLK, this can be a /32 divider between TRxC and RTxC.
  126.  *        When the clock is at RTxC, the TX rate must be supplied at TRxC.
  127.  *        This is needed only for AX.25 fullduplex.
  128.  *        When this arg is given as "ext", the transmit and receive clock
  129.  *        are external, and the BRG and DPLL are not used.
  130.  * argv[6]: callsign used on the radio channels
  131.  */
  132.  
  133. int
  134. scc_attach(argc,argv)
  135. int argc;
  136. char *argv[];
  137. {
  138.     register struct interface *ifp;
  139.     struct sccchan *scc;
  140.     unsigned int chan,brgrate;
  141.     int pclk = 0;
  142.     char *p;
  143.     char r11;
  144.     int hwtype = 0,hwparam = 0;
  145. #ifdef ATARI_ST
  146.     long save_ssp;
  147. #endif
  148.     extern struct interface *ifaces;
  149.     int slip_send(),kiss_ioctl(),kiss_raw();
  150.     void kiss_recv(),slip_recv();
  151.     long atol(),htol();
  152.  
  153.     /* first handle the special "init" mode, to initialize global stuff */
  154.  
  155.     if(!strcmp(argv[2],"init")){
  156.     if(argc < 11)            /* need at least argv[1]..argv[10] */
  157.         return -1;
  158.  
  159.     if (isupper(argv[10][0]))
  160.         argv[10][0] = tolower(argv[10][0]);
  161.  
  162.     if (argv[10][0] == 'p'){    /* wants to use PCLK as clock? */
  163.         pclk = 1;
  164.         argv[10]++;
  165.     } else {
  166.         if (argv[10][0] == 'r')    /* wants to use RTxC? */
  167.         argv[10]++;        /* that's the default */
  168.     }
  169.  
  170.     if (argc > 11)            /* optional hardware type */
  171.         hwtype = htoi(argv[11]);    /* it is given in hex */
  172.  
  173.     if (argc > 12)            /* optional hardware param */
  174.         hwparam = htoi(argv[12]);    /* also in hex */
  175.  
  176.     return scc_init(atoi(argv[1]),(ioaddr) htol(argv[3]),atoi(argv[4]),
  177.             atoi(argv[5]),atoi(argv[6]),atoi(argv[7]),
  178.             (ioaddr) htol(argv[8]),atoi(argv[9]),
  179.             atol(argv[10]),pclk,hwtype,hwparam);
  180.     }
  181.  
  182.     /* not "init", so it must be a valid mode to attach a channel */
  183.  
  184.     if (strcmp(argv[2],"ax25") && strcmp(argv[2],"kiss") &&
  185.     strcmp(argv[2],"slip")){
  186.     printf("Mode %s unknown for SCC\n",argv[2]);
  187.     return -1;
  188.     }
  189.  
  190.     if (!sccinfo.init){
  191.     printf("First init SCC driver\n");
  192.     return -1;
  193.     }
  194.  
  195.     if ((chan = atoi(argv[1])) > sccinfo.maxchan){
  196.     printf("SCC channel %d out of range\n",chan);
  197.     return -1;
  198.     }
  199.  
  200.     if (sccchan[chan] != NULLCHAN){
  201.     printf("SCC channel %d already attached\n",chan);
  202.     return -1;
  203.     }
  204.  
  205.     /* create interface structure and fill in details */
  206.  
  207.     if ((ifp = (struct interface *) calloc(1,sizeof(struct interface))) == NULLIF){
  208.     printf(nospace);
  209.     return -1;
  210.     }
  211.  
  212.     if ((ifp->name = malloc(strlen(argv[3]) + 1)) == NULLCHAR){
  213.     printf(nospace);
  214.     free(ifp);
  215.     return -1;
  216.     }
  217.     strcpy(ifp->name,argv[3]);
  218.  
  219.     ifp->mtu = atoi(argv[4]);
  220.     ifp->dev = chan;
  221.     ifp->recv = doscc;
  222.     ifp->stop = scc_stop;
  223.  
  224.     if ((scc = (struct sccchan *) calloc(1,sizeof(struct sccchan))) == NULLCHAN){
  225.     printf(nospace);
  226.     free(ifp->name);
  227.     free(ifp);
  228.     return -1;
  229.     }
  230.  
  231.     scc->ctrl = sccinfo.iobase + (chan / 2) * sccinfo.space + sccinfo.off[chan % 2];
  232.     scc->data = scc->ctrl + sccinfo.doff;
  233.     scc->iface = ifp;
  234.  
  235.     sccchan[chan] = scc;        /* put addr in table for interrupts */
  236.  
  237.     switch (argv[2][0])            /* mode already checked above */
  238.     {
  239.     case 'a':                /* AX.25 */
  240.     /* default: RXclk DPLL, TXclk BRG. BRG reprogrammed at every TX/RX switch */
  241.     r11 = RCDPLL|TCBR;
  242.  
  243.     /* check for options ('d', 'ext') in the baudrate field */
  244.  
  245.     if (isupper(argv[5][0]))
  246.         argv[5][0] = tolower(argv[5][0]);
  247.  
  248.     switch (argv[5][0])
  249.     {
  250.     case 'd':            /* fulldup divider installed? */
  251.         scc->flags |= DIVIDER;    /* set appropriate flag */
  252.         argv[5]++;            /* skip the 'd' */
  253.  
  254.         if (sccinfo.pclk){        /* when using PCLK as clock source */
  255.         /* RXclk DPLL, TXclk RTxC, out=BRG.  external /32 TRxC->RTxC */
  256.         r11 = RCDPLL|TCRTxCP|TRxCOI|TRxCBR;
  257.         } else {
  258.         /* RXclk DPLL, TXclk TRxC.  external TX clock to TRxC */
  259.         r11 = RCDPLL|TCTRxCP;
  260.         }
  261.         break;
  262.  
  263.     case 'e':            /* external clocking? */
  264.         scc->flags |= EXTCLOCK;    /* set the flag */
  265.         r11 = RCRTxCP|TCTRxCP;    /* RXclk RTxC, TXclk TRxC. */
  266.         break;
  267.     }
  268.  
  269.     /* option :hexvalue at end of baudrates allows custom R11 setup */
  270.  
  271.     if ((p = strchr(argv[5],':')) != NULLCHAR){
  272.         *p++ = 0;
  273.         r11 = htoi(p);
  274.     }
  275.  
  276. #ifdef ATARI_ST
  277.     save_ssp = Super(NULL);        /* enter supervisor mode */
  278. #endif
  279.  
  280.     scc_sdlc(scc,r11);        /* init SCC in SDLC mode */
  281.  
  282.     if (!(scc->flags & EXTCLOCK)) {
  283.         brgrate = scc_speed(scc,32,atol(argv[5]));/* init SCC speed */
  284.         scc->speed = sccinfo.clk / (64L * (brgrate + 2));/* calc real speed */
  285.     }
  286.  
  287. #ifdef ATARI_ST
  288.     Super(save_ssp);        /* back to user mode */
  289. #endif
  290.  
  291.     /* default KISS Params */
  292.     scc->c.a.params[TXDELAY] = 36*TPS/100;    /* 360 ms */
  293.     scc->c.a.params[PERSIST] = 25;        /* 10% persistence */
  294.     scc->c.a.params[SLOTTIME] = 16*TPS/100; /* 160 ms */
  295.     scc->c.a.params[TAILTIME] = TPS>67? 3*TPS/100:2; /* 30 ms */
  296.     scc->c.a.params[FULLDUP] = 0;        /* CSMA */
  297.     scc->c.a.params[TNCSPECIF] = 1;        /* DTR set */
  298.     scc->c.a.params[WAITTIME] = 50*TPS/100; /* 500 ms */
  299.     scc->c.a.params[MAXKEYUP] = 7;        /* 7 s */
  300.     scc->c.a.params[MINTIME] = 3;        /* 3 s */
  301.     scc->c.a.params[IDLETIME] = 120;    /* 120 s */
  302.  
  303.     if (scc_ax25(ifp,argv[2],argv[6])){ /* init AX.25 mode */
  304.         scc_stop(ifp);
  305.         free(ifp->name);
  306.         free(ifp);
  307.         return -1;
  308.     }
  309.  
  310.     ifp->ioctl = scc_sioctl;
  311.     ifp->raw = scc_raw;
  312.     scc->recv = scc_recv;
  313.     break;
  314.  
  315.     case 'k':                /* kiss */
  316. #ifdef ATARI_ST
  317.     save_ssp = Super(NULL);        /* enter supervisor mode */
  318. #endif
  319.     scc_async(scc);            /* init SCC in async mode */
  320.     brgrate = scc_speed(scc,16,atol(argv[5]));/* init SCC speed */
  321.     scc->speed = sccinfo.clk / (32L * (brgrate + 2));/* calc real speed */
  322. #ifdef ATARI_ST
  323.     Super(save_ssp);        /* back to user mode */
  324. #endif
  325.  
  326.     if (scc_ax25(ifp,argv[2],argv[6])){ /* init AX.25 mode */
  327.         scc_stop(ifp);
  328.         free(ifp->name);
  329.         free(ifp);
  330.         return -1;
  331.     }
  332.  
  333.     ifp->ioctl = kiss_ioctl;
  334.     ifp->raw = kiss_raw;
  335.     ifp->slipraw = scc_slipraw;
  336.     scc->recv = kiss_recv;
  337.     break;
  338.  
  339.     case 's':                /* slip */
  340. #ifdef ATARI_ST
  341.     save_ssp = Super(NULL);        /* enter supervisor mode */
  342. #endif
  343.     scc_async(scc);            /* init SCC in async mode */
  344.     brgrate = scc_speed(scc,16,atol(argv[5]));/* init SCC speed */
  345.     scc->speed = sccinfo.clk / (32L * (brgrate + 2));/* calc real speed */
  346. #ifdef ATARI_ST
  347.     Super(save_ssp);        /* back to user mode */
  348. #endif
  349.  
  350.     ifp->ioctl = scc_aioctl;
  351.     ifp->send = slip_send;
  352.     ifp->output = NULLFP;        /* ARP isn't used */
  353.     ifp->raw = ifp->slipraw = scc_slipraw;
  354.     scc->recv = slip_recv;
  355.     break;
  356.     }
  357.  
  358.     ifp->next = ifaces;            /* link interface in list */
  359.     ifaces = ifp;
  360.     return 0;
  361. }
  362.  
  363. /* SCC driver initialisation. called on "attach scc <num> init ..." */
  364. /* on the Atari ST, processor must be in supervisor mode */
  365. static int
  366. scc_init(nchips,iobase,space,aoff,boff,doff,intack,ivec,clk,pclk,hwtype,hwparam)
  367.     int nchips;                /* number of chips */
  368.     ioaddr iobase;            /* base of first chip */
  369.     int space,aoff,boff,doff;
  370.     ioaddr intack;            /* INTACK ioport or 0 for no INTACK */
  371.     int ivec;                /* interrupt vector number */
  372.     long clk;                /* clock frequency */
  373.     int pclk;                /* PCLK or RTxC for clock */
  374.     int hwtype;                /* selection of special hardware types */
  375.     int hwparam;            /* extra parameter for special hardware */
  376.  
  377. {
  378.     int chip,chan;
  379.     ioaddr chipbase;
  380.     register ioaddr ctrl;
  381.     int i_state,d;
  382.     int dum = 1;
  383. #ifdef ATARI_ST
  384.     int z = 0;                /* to avoid clear instruction (68000) */
  385.     long save_ssp;            /* saved stackpointer for Super() */
  386.     static char gpipbit[] = {0,1,2,3,8,8,4,5,8,8,8,8,8,8,6,7};
  387.     extern void sccvec(),sccnovec(),scctvec(); /* interrupt handlers */
  388. #endif
  389. #ifdef MSDOS
  390. # define z 0
  391. # ifdef SCC_HWTIMER
  392.     time_t time1,time2;
  393. # endif
  394.     extern void sccvec(),sccnovec(),scctvec(); /* interrupt handlers */
  395.     void (*getirq())();        /* Getirq is a function returning a pointer to
  396.                  * a function returning void */
  397. # ifndef __TURBOC__
  398.     void (*getvect())();    /* Getvect too! */
  399. # endif
  400. #endif
  401.  
  402.     if (sccinfo.init){
  403.     printf("SCC driver already initialized - nothing done\n");
  404.     return 1;
  405.     }
  406.  
  407.     sccinfo.init = 1;
  408.     sccinfo.nchips = nchips;
  409.     sccinfo.maxchan = (2 * nchips) - 1;
  410.     sccinfo.iobase = iobase;
  411.     sccinfo.space = space;
  412.     sccinfo.off[0] = aoff;
  413.     sccinfo.off[1] = boff;
  414.     sccinfo.doff = doff;
  415.     sccinfo.ivec = ivec;
  416.     sccinfo.clk = clk;
  417.     sccinfo.pclk = pclk;
  418.     sccinfo.hwtype = hwtype;
  419.     sccinfo.hwparam = hwparam;
  420.  
  421. #ifdef ATARI_ST
  422.     save_ssp = Super(NULL);        /* enter supervisor mode */
  423. #endif
  424.  
  425.     /* reset and pre-init all chips in the system */
  426.     for (chip = 0; chip < nchips; chip++){
  427.     chipbase = iobase + chip * space;
  428.     ctrl = chipbase + sccinfo.off[0];
  429.  
  430.     i_state = disable();        /* because of 2-step accesses */
  431.  
  432.     VOID(RDREG(ctrl));        /* make sure pointer is written */
  433.     WRSCC(ctrl,R9,FHWRES);        /* force hardware reset */
  434.  
  435.     for (d = 0; d < 1000; d++)    /* wait a while to be sure */
  436.         dum *= 10;
  437.  
  438.     for (chan = 0; chan < 2; chan++){
  439.         ctrl = chipbase + sccinfo.off[chan];
  440.  
  441.         /* initialize a single channel to no-op */
  442.  
  443.         VOID(RDREG(ctrl));        /* make sure pointer is written */
  444.         WRSCC(ctrl,R4,z);        /* no mode selected yet */
  445.         WRSCC(ctrl,R1,z);        /* no W/REQ operation */
  446.         WRSCC(ctrl,R2,16 * chip);    /* chip# in upper 4 bits of vector */
  447.         WRSCC(ctrl,R3,z);        /* disable rx */
  448.         WRSCC(ctrl,R5,z);        /* disable tx */
  449.         WRSCC(ctrl,R9,VIS);        /* vector includes status, MIE off */
  450.  
  451.         sccpolltab[chip][chan] = ctrl; /* store ctrl addr for polling */
  452.     }
  453.  
  454. #ifdef MSDOS
  455.     if (hwtype & EAGLE)        /* this is an EAGLE card */
  456.         WRREG(chipbase + 4,0x08);    /* enable interrupt on the board */
  457.  
  458.     if (hwtype & PC100)        /* this is a PC100 card */
  459.         WRREG(chipbase,hwparam);    /* set the MODEM mode (22H normally) */
  460.  
  461.     if (hwtype & PRIMUS)        /* this is a PRIMUS-PC */
  462.         WRREG(chipbase + 4,hwparam); /* set the MODEM mode (02H normally) */
  463.  
  464.     if (hwtype & DRSI)        /* this is a DRSI PC*Packet card */
  465.     {
  466.         ioaddr z8536 = chipbase + 7; /* point to 8536 master ctrl reg */
  467.  
  468.         /* Initialize 8536 to perform its divide-by-32 function */
  469.         /* This part copied from N6TTO DRSI-driver */
  470.  
  471.         /* Start by forcing chip into known state */
  472.  
  473.         VOID(RDREG(z8536));        /* make sure pointer is written */
  474.         WRSCC(z8536,CIO_MICR,0x01); /* force hardware reset */
  475.  
  476.         for (d = 0; d < 1000; d++)    /* wait a while to be sure */
  477.         dum *= 10;
  478.  
  479.         WRSCC(z8536,CIO_MICR,0x00); /* Clear reset and start */
  480.  
  481.         /* Wait for chip to come ready */
  482.  
  483.         while (RDSCC(z8536,CIO_MICR) != 0x02)
  484.         dum *= 10;
  485.  
  486.         WRSCC(z8536,CIO_MICR,0x26); /* NV|CT_VIS|RJA */
  487.         WRSCC(z8536,CIO_MCCR,0xf4); /* PBE|CT1E|CT2E|CT3E|PAE */
  488.  
  489.         WRSCC(z8536,CIO_CTMS1,0xe2);/* Continuous, EOE, ECE, Pulse output */
  490.         WRSCC(z8536,CIO_CTMS2,0xe2);/* Continuous, EOE, ECE, Pulse output */
  491.  
  492.         WRSCC(z8536,CIO_CT1MSB,0x00); /* Load time constant CTC #1 */
  493.         WRSCC(z8536,CIO_CT1LSB,0x10);
  494.         WRSCC(z8536,CIO_CT2MSB,0x00); /* Load time constant CTC #2 */
  495.         WRSCC(z8536,CIO_CT2LSB,0x10);
  496.  
  497.         WRSCC(z8536,CIO_IVR,0x06);
  498.  
  499.         /* Set port direction bits in port A and B             */
  500.         /* Data is input on bits d1 and d5, output on d0 and d4. */
  501.         /* The direction is set by 1 for input and 0 for output  */
  502.  
  503.         WRSCC(z8536,CIO_PDCA,0x22);
  504.         WRSCC(z8536,CIO_PDCB,0x22);
  505.  
  506.         WRSCC(z8536,CIO_CSR1,CIO_GCB|CIO_TCB); /* Start CTC #1 running */
  507.         WRSCC(z8536,CIO_CSR2,CIO_GCB|CIO_TCB); /* Start CTC #2 running */
  508.     }
  509. #endif
  510.  
  511.     restore(i_state);
  512.     }
  513.  
  514. #ifdef ATARI_ST
  515.     Super(save_ssp);            /* back to user mode */
  516. #endif
  517.  
  518.     sccpolltab[chip][0] = 0;        /* terminate the polling table */
  519.     sccvecloc = intack;            /* location of INTACK/vector read */
  520.     sccmaxvec = 16 * nchips;        /* upper limit on valid vector */
  521.  
  522. #ifdef ATARI_ST
  523.     sccgpiploc = (ioaddr) 0xfffa01L;    /* location of GPIP */
  524.     sccgpipbit = gpipbit[ivec];        /* bit number in GPIP */
  525.     sccisrloc = (ioaddr) (ivec > 7? 0xfffa0fL : 0xfffa11L); /* location of ISR */
  526.     sccisrbit = ivec % 8;        /* bit number in ISR */
  527.  
  528.     if (intack){            /* INTACK method selected? */
  529.     /*  set interrupt vector to INTACK-generating routine  */
  530.     Mfpint(ivec,sccvec);
  531.     } else {
  532.     /*  set interrupt vector to polling routine */
  533.     Mfpint(ivec,sccnovec);
  534.     }
  535.  
  536.     Jenabint(ivec);            /* enable the interrupt */
  537.  
  538.     i_state = disable();
  539.     sccotvec = (void (*)()) Setexc(0x114/4,scctvec); /* install timer interrupt vector */
  540.     restore(i_state);
  541. #endif
  542. #ifdef MSDOS
  543.     /*    save original interrupt vector    */
  544.     orgivec = getirq(ivec);
  545.  
  546.     if (intack){            /* INTACK method selected? */
  547.     /*  set interrupt vector to INTACK-generating routine  */
  548.     setirq(ivec,sccvec);
  549.     } else {
  550.     /*  set interrupt vector to polling routine */
  551.     setirq(ivec,sccnovec);
  552.     }
  553.  
  554.     /*    enable the interrupt  */
  555.     maskon(ivec);
  556.  
  557.     /* get original timer interrupt vector */
  558.  
  559. # ifdef SCC_HWTIMER
  560.     sccotvec = getirq(0);
  561. # else
  562.     sccotvec = getvect(0x1c);
  563. # endif
  564.  
  565.     /* install timer interrupt handler (that jumps to the original) */
  566.  
  567.     TPS = 18;                    /* standard ticks/second */
  568.  
  569. # ifdef SCC_HWTIMER
  570.     setirq(0,scctvec);                /* install on hardware int */
  571.  
  572. #  if (defined(MSC) || defined(__TURBOC__))
  573.     /* find the number of ticks per second the hardware timer generates */
  574.  
  575.     time1 = time(NULL);
  576.  
  577.     while ((time2 = time(NULL)) == time1)    /* wait for seconds mark */
  578.        ;
  579.  
  580.     sccinfo.ticks = 0;                /* clear tally */
  581.     time2 += 4;                    /* setup a 4-second wait */
  582.  
  583.     while (time(NULL) < time2)            /* wait 4 seconds */
  584.        ;
  585.  
  586.     if ((TPS = (sccinfo.ticks + 2) / 4) < 18)    /* compute ticks */
  587.     printf("WARNING: SCC timer problem\n");
  588.     else
  589.     printf("SCC: %u ticks/s, %u ms/tick\n",TPS,
  590.            (8000 + sccinfo.ticks) / (2 * sccinfo.ticks));
  591. #  endif
  592. # else
  593.     setvect(0x1c,scctvec);            /* install on software int */
  594. # endif
  595. #endif
  596.  
  597.     return 0;
  598. }
  599.  
  600. /* initialize an SCC channel in asynchronous mode */
  601. /* on the Atari ST, processor must be in supervisor mode */
  602. static void
  603. scc_async(scc)
  604.     register struct sccchan *scc;
  605.  
  606. {
  607.     int i_state;
  608.     void scc_asytx(),scc_asyex(),scc_asyrx(),scc_asysp(); /* int handlers */
  609. #ifdef ATARI_ST
  610.     int z = 0;                /* to avoid clear instruction (68000) */
  611. #endif
  612.  
  613.     scc->int_transmit = scc_asytx;    /* set interrupt handlers */
  614.     scc->int_extstat = scc_asyex;
  615.     scc->int_receive = scc_asyrx;
  616.     scc->int_special = scc_asysp;
  617.  
  618.     i_state = disable();
  619.  
  620.     wr(scc,R4,X16CLK|SB1);        /* *16 clock, 1 stopbit, no parity */
  621.     wr(scc,R1,z);            /* no W/REQ operation */
  622.     wr(scc,R3,Rx8);            /* RX 8 bits/char, disabled */
  623.     wr(scc,R5,Tx8|DTR|RTS);        /* TX 8 bits/char, disabled, DTR RTS */
  624.     wr(scc,R9,VIS);            /* vector includes status */
  625.     wr(scc,R10,NRZ|z);            /* select NRZ */
  626.     wr(scc,R11,RCBR|TCBR);        /* clocks are BR generator */
  627.     wr(scc,R14,sccinfo.pclk? BRSRC:z);    /* brg source = PCLK/RTxC */
  628.     wr(scc,R15,BRKIE);            /* enable BREAK ext/status int */
  629.  
  630.     or(scc,R3,RxENABLE);        /* enable receiver */
  631.     or(scc,R5,TxENAB);            /* enable transmitter */
  632.  
  633.     WRREG(scc->ctrl,RES_EXT_INT);    /* reset ext/status interrupts */
  634.     WRREG(scc->ctrl,RES_EXT_INT);    /* must be done twice */
  635.     scc->status = RDREG(scc->ctrl);    /* read initial status */
  636.  
  637.     or(scc,R1,INT_ALL_Rx|TxINT_ENAB|EXT_INT_ENAB); /* enable interrupts */
  638.     or(scc,R9,MIE);            /* master interrupt enable */
  639.  
  640.     restore(i_state);
  641. }
  642.  
  643. /* initialize an SCC channel in SDLC mode */
  644. /* on the Atari ST, processor must be in supervisor mode */
  645. static void
  646. scc_sdlc(scc,r11)
  647.     register struct sccchan *scc;
  648.     char r11;                /* clockmode to load in WR11 */
  649.  
  650. {
  651.     int i_state;
  652.     void scc_sdlctx(),scc_sdlcex(),scc_sdlcrx(),scc_sdlcsp(); /* int handlers */
  653. #ifdef ATARI_ST
  654.     int z = 0;                /* to avoid clear instruction (68000) */
  655. #endif
  656.  
  657.     scc->int_transmit = scc_sdlctx;    /* set interrupt handlers */
  658.     scc->int_extstat = scc_sdlcex;
  659.     scc->int_receive = scc_sdlcrx;
  660.     scc->int_special = scc_sdlcsp;
  661.  
  662.     i_state = disable();
  663.  
  664.     wr(scc,R4,X1CLK|SDLC);        /* *1 clock, SDLC mode */
  665.     wr(scc,R1,z);            /* no W/REQ operation */
  666.     wr(scc,R3,Rx8|RxCRC_ENAB);        /* RX 8 bits/char, CRC, disabled */
  667.     wr(scc,R5,Tx8|DTR|TxCRC_ENAB);    /* TX 8 bits/char, disabled, DTR */
  668.     wr(scc,R6,z);            /* SDLC address zero (not used) */
  669.     wr(scc,R7,FLAG);            /* SDLC flag value */
  670.     wr(scc,R9,VIS);            /* vector includes status */
  671.     wr(scc,R10,CRCPS|NRZI|ABUNDER);    /* CRC preset 1, select NRZI, ABORT on underrun */
  672.     wr(scc,R11,r11);            /* clockmode as determined before */
  673.  
  674.     if (scc->flags & EXTCLOCK){        /* when using external clocks */
  675.     wr(scc,R14,z);            /* No BRG options */
  676.     WRSCC(scc->ctrl,R14,DISDPLL|scc->wreg[R14]); /* No DPLL operation */
  677.     } else {
  678.     wr(scc,R14,sccinfo.pclk? BRSRC:z); /* BRG source = PCLK/RTxC */
  679.     WRSCC(scc->ctrl,R14,SSBR|scc->wreg[R14]); /* DPLL source = BRG */
  680.     WRSCC(scc->ctrl,R14,SNRZI|scc->wreg[R14]); /* DPLL NRZI mode */
  681.     }
  682.  
  683.     wr(scc,R15,BRKIE|CTSIE|DCDIE);    /* enable ABORT, CTS & DCD interrupts */
  684.  
  685.     if (RDREG(scc->ctrl) & DCD){    /* DCD is now ON */
  686.     if (!(scc->flags & EXTCLOCK))
  687.         WRSCC(scc->ctrl,R14,SEARCH|scc->wreg[R14]); /* DPLL: enter search mode */
  688.     or(scc,R3,ENT_HM|RxENABLE);    /* enable the receiver, hunt mode */
  689.     }
  690.  
  691.     WRREG(scc->ctrl,RES_EXT_INT);    /* reset ext/status interrupts */
  692.     WRREG(scc->ctrl,RES_EXT_INT);    /* must be done twice */
  693.     scc->status = RDREG(scc->ctrl);    /* read initial status */
  694.  
  695.     or(scc,R1,INT_ALL_Rx|TxINT_ENAB|EXT_INT_ENAB); /* enable interrupts */
  696.     or(scc,R9,MIE);            /* master interrupt enable */
  697.  
  698.     restore(i_state);
  699. }
  700.  
  701. /* set SCC channel speed */
  702. /* clkmode specifies the division rate (1,16,32) inside the SCC */
  703. /* on the Atari ST, processor must be in supervisor mode */
  704. /* returns the selected brgrate for "real speed" calculation */
  705.  
  706. static unsigned int scc_speed(scc,clkmode,speed)
  707.     register struct sccchan *scc;
  708.     unsigned int clkmode;
  709.     long speed;                /* the desired baudrate */
  710.  
  711. {
  712.     unsigned int brgrate;
  713.     long spdclkm;
  714.     int i_state;
  715.  
  716.     /* calculate baudrate generator value */
  717.  
  718.     if ((spdclkm = speed * clkmode) == 0)
  719.     return 65000U;            /* avoid divide-by-zero */
  720.  
  721.     brgrate = (unsigned) ((sccinfo.clk + spdclkm) / (spdclkm * 2)) - 2;
  722.  
  723.     i_state = disable();        /* 2-step register accesses... */
  724.  
  725.     cl(scc,R14,BRENABL);        /* disable baudrate generator */
  726.     wr(scc,R12,brgrate);        /* brg rate LOW */
  727.     wr(scc,R13,brgrate >> 8);        /* brg rate HIGH */
  728.     or(scc,R14,BRENABL);        /* enable baudrate generator */
  729.  
  730.     restore(i_state);
  731.  
  732.     return brgrate;
  733. }
  734.  
  735. /* de-activate SCC channel */
  736. static int
  737. scc_stop(ifp)
  738.     struct interface *ifp;
  739.  
  740. {
  741.     struct sccchan *scc = sccchan[ifp->dev];
  742.     int i_state;
  743. #ifdef ATARI_ST
  744.     long save_ssp;
  745.  
  746.     save_ssp = Super(NULL);        /* enter supervisor mode */
  747. #endif
  748.  
  749.     i_state = disable();
  750.  
  751.     VOID(RDREG(scc->ctrl));        /* make sure pointer is written */
  752.     wr(scc,R9,(ifp->dev % 2)? CHRB : CHRA); /* reset the channel */
  753.     free(scc);
  754.     sccchan[ifp->dev] = NULLCHAN;
  755.  
  756.     restore(i_state);
  757.  
  758. #ifdef ATARI_ST
  759.     Super(save_ssp);            /* back to user mode */
  760. #endif
  761. }
  762.  
  763. /* de-activate SCC driver on program exit */
  764. void sccstop()
  765.  
  766. {
  767.     if (sccinfo.init){            /* was it initialized? */
  768. #ifdef ATARI_ST
  769.     Jdisint(sccinfo.ivec);        /* disable the interrupt */
  770.     Setexc(0x114/4,sccotvec);    /* reset the timer vector */
  771. #endif
  772. #ifdef MSDOS
  773.     maskoff(sccinfo.ivec);        /* disable the interrupt */
  774.     setirq(sccinfo.ivec,orgivec);    /* restore original interrupt vector */
  775. # ifdef SCC_HWTIMER
  776.     setirq(0,sccotvec);        /* restore original timer interrupt */
  777. # else
  778.     setvect(0x1c,sccotvec);        /* same, but using INT 1CH */
  779. # endif
  780. #endif
  781.     }
  782. }
  783.  
  784. /* perform ioctl on SCC (async) channel */
  785. /* this is used for SLIP mode only, and will read/set the line speed */
  786. static int
  787. scc_aioctl(ifp,argc,argv)
  788.     struct interface *ifp;
  789.     int argc;
  790.     char *argv[];
  791.  
  792. {
  793.     struct sccchan *scc;
  794.     unsigned int brgrate;
  795. #ifdef ATARI_ST
  796.     long save_ssp;
  797. #endif
  798.  
  799.     scc = sccchan[ifp->dev];
  800.  
  801.     if (argc < 1){
  802.     printf("%ld\n",scc->speed);
  803.     return 0;
  804.     }
  805.  
  806. #ifdef ATARI_ST
  807.     save_ssp = Super(NULL);        /* enter supervisor mode */
  808. #endif
  809.  
  810.     brgrate = scc_speed(scc,16,atol(argv[0]));
  811.     scc->speed = sccinfo.clk / (32L * (brgrate + 2));
  812.  
  813. #ifdef ATARI_ST
  814.     Super(save_ssp);            /* back to user mode */
  815. #endif
  816.  
  817.     return 0;
  818. }
  819.  
  820. /* perform ioctl on SCC (sdlc) channel */
  821. /* this is used for AX.25 mode only, and will set the "kiss" parameters */
  822. static int
  823. scc_sioctl(ifp,argc,argv)
  824.     struct interface *ifp;
  825.     int argc;
  826.     char *argv[];
  827.  
  828. {
  829.     struct sccchan *scc;
  830.     int param,i_state;
  831.     unsigned int brgrate;
  832.     char *p;
  833. #ifdef ATARI_ST
  834.     long save_ssp;
  835. #endif
  836.  
  837.     scc = sccchan[ifp->dev];
  838.  
  839.     if (argc == 0){
  840.     if (scc->flags & EXTCLOCK)
  841.         printf("ext.clk:%02x",scc->wreg[R11]);
  842.     else
  843.         printf("speed=%s%ld:%02x",(scc->flags & DIVIDER)? "d":"",
  844.                       scc->speed,scc->wreg[R11]);
  845.  
  846.     printf(" group=%03x tx=%c",scc->group,(scc->flags & TX_INHIBIT)? 'n':'y');
  847.  
  848.     for (param = 1; param < sizeof(scc->c.a.params); param++)
  849.         printf(" %d=%d",param,scc->c.a.params[param]);
  850.  
  851.     printf("\n");
  852.     return 0;
  853.     }
  854.  
  855.     if (argc < 2){
  856.     printf("Data field missing\n");
  857.     return 1;
  858.     }
  859.  
  860.     switch (argv[0][0])            /* check special param setting */
  861.     {
  862.     case 'g':                /* setting of group */
  863.     scc->group = htoi(argv[1]);
  864.     return 0;
  865.  
  866.     case 's':                /* setting of speed */
  867.     if (!(scc->flags & EXTCLOCK)) {
  868. #ifdef ATARI_ST
  869.         save_ssp = Super(NULL);    /* enter supervisor mode */
  870. #endif
  871.         /* option :hexvalue at end of baudrates allows custom R11 setup */
  872.  
  873.         if ((p = strchr(argv[1],':')) != NULLCHAR){
  874.         *p++ = 0;
  875.         i_state = disable();
  876.         wr(scc,R11,htoi(p));    /* set new R11 value */
  877.         restore(i_state);
  878.         }
  879.  
  880.         brgrate = scc_speed(scc,32,atol(argv[1]));/* init SCC speed */
  881.         scc->speed = sccinfo.clk / (64L * (brgrate + 2));/* calc real speed */
  882. #ifdef ATARI_ST
  883.         Super(save_ssp);        /* back to user mode */
  884. #endif
  885.     }
  886.     return 0;
  887.  
  888.     case 't':                /* set tx inhibit */
  889.     if (tolower(argv[1][0]) == 'n')
  890.         scc->flags |= TX_INHIBIT;    /* no tx = inhibit it */
  891.     else
  892.         scc->flags &= ~TX_INHIBIT;
  893.     return 0;
  894.     }
  895.  
  896.     if ((param = atoi(argv[0])) <= 0 || param >= sizeof(scc->c.a.params)){
  897.     printf("Param number out of range\n");
  898.     return 1;
  899.     }
  900.  
  901.     scc->c.a.params[param] = atoi(argv[1]);
  902.  
  903.     /* and now, a special hack to allow setting of DTR with param #6 */
  904.  
  905.     if (param == TNCSPECIF){
  906.     i_state = disable();
  907.  
  908.     if (scc->c.a.params[TNCSPECIF]) /* set or clear DTR image bit */
  909.         scc->wreg[R5] |= DTR;
  910.     else
  911.         scc->wreg[R5] &= ~DTR;
  912.  
  913.     if (scc->c.a.tstate == IDLE && scc->timercount == 0)
  914.         scc->timercount = 1;    /* force an update */
  915.  
  916.     restore(i_state);
  917.     }
  918.  
  919.     return 0;
  920. }
  921.  
  922. /* start SCC transmitter when it is idle (SLIP/KISS mode only) */
  923. static void
  924. scc_sstart(scc)
  925.     register struct sccchan *scc;
  926. {
  927. #ifdef ATARI_ST
  928.     long save_ssp;
  929. #endif
  930.  
  931.     if (scc->c.s.tbp != NULLBUF ||    /* busy */
  932.     scc->c.s.sndq == NULLBUF)    /* no work */
  933.     return;
  934.  
  935.     scc->c.s.tbp = dequeue(&scc->c.s.sndq);
  936.  
  937. #ifdef ATARI_ST
  938.     save_ssp = Super(NULL);        /* enter supervisor mode */
  939. #endif
  940.  
  941.     WRREG(scc->data,FR_END);        /* write first char to start things */
  942.  
  943. #ifdef ATARI_ST
  944.     Super(save_ssp);            /* back to user mode */
  945. #endif
  946. }
  947.  
  948. /* show SCC status */
  949. dosccstat()
  950. {
  951.     register struct sccchan *scc;
  952.     int i;
  953.  
  954.     if (!sccinfo.init){
  955.     printf("SCC driver not initialized\n");
  956.     return 0;
  957.     }
  958.  
  959.     printf("Ch Iface    Sent   Rcvd   Error Space Overr   Rxints   Txints   Exints   Spints\n");
  960.  
  961.     for (i = 0; i <= sccinfo.maxchan; i++) {
  962.     if ((scc = sccchan[i]) == NULLCHAN)
  963.         continue;
  964.  
  965.     printf("%2d %-6s %6lu %6lu %7lu %5u %5u %8lu %8lu %8lu %8lu\n",i,scc->iface->name,
  966.         scc->enqueued,scc->rxframes,scc->rxerrs,scc->nospace,scc->rovers,
  967.         scc->rxints,scc->txints,scc->exints,scc->spints);
  968.     }
  969.  
  970.     return 0;
  971. }
  972.  
  973. /* process incoming packets. called from main loop to poll rx queue. */
  974. static int
  975. doscc(ifp)
  976.     struct interface *ifp;
  977.  
  978. {
  979.     register struct sccchan *scc;
  980.     int rv = 0;
  981.  
  982.     scc = sccchan[ifp->dev];
  983.  
  984.     while (scc->rqueue != NULLBUF) {    /* incoming packets waiting? */
  985.     (*scc->recv)(ifp,dequeue(&scc->rqueue)); /* process first */
  986.     rv++;
  987.     }
  988.  
  989. #ifdef ATARI_ST
  990.     /* it seems that the MFP sometimes misses the interrupt edge
  991.      * if this happens, no more interrupts occur and the SCC's hang.
  992.      * test if the int input is low, and panic if so.
  993.      */
  994.     if (ifp->dev == 0){
  995.     long save_ssp;
  996.     unsigned char bit;
  997.     int i_state;
  998.     static int intcntr = 0;
  999.     static int trycntr = 0;
  1000.     static char mesg1[] = "WARNING: SCC IRQ stuck, recover";
  1001.     static char mesg2[] = "PANIC: SCC IRQ stuck, exit";
  1002.  
  1003.     save_ssp = Super(NULL);        /* enter supervisor mode */
  1004.     bit = RDREG(sccgpiploc);    /* test interrupt level */
  1005.     bit |= RDREG(sccgpiploc);    /* 2nd time to avoid glitch */
  1006.     Super(save_ssp);        /* back to user mode */
  1007.  
  1008.     if (!(bit & (1 << sccgpipbit))){ /* int active now? */
  1009.         if (++intcntr > 10) {    /* was that true the last 10 times? */
  1010.         if (trycntr++ == 0) {    /* check for recovery phase */
  1011.             log_msg(mesg1);
  1012.             printf("%s\n",mesg1);
  1013.             save_ssp = Super(NULL); /* enter supervisor mode */
  1014.             i_state = disable();
  1015.  
  1016.             if (sccvecloc)    /* INTACK method selected? */
  1017.             sccvec();    /* call vectored handler */
  1018.             else
  1019.             sccnovec();    /* else use non-vectored handler */
  1020.  
  1021.             restore(i_state);
  1022.             Super(save_ssp);    /* back to user mode */
  1023.         } else {        /* already recovering... */
  1024.             log_msg(mesg2);    /* make it a PANIC */
  1025.             printf("%s\n",mesg2);
  1026.             doexit(0);
  1027.         }
  1028.         }
  1029.     } else {
  1030.         intcntr = trycntr = 0;    /* not active, count back to 0 */
  1031.     }
  1032.     }
  1033. #endif
  1034.  
  1035.     return rv;                /* number of processed packets */
  1036. }
  1037.  
  1038. /* process received frame on SCC. used for AX.25 mode only */
  1039. static void
  1040. scc_recv(ifp,bp)
  1041.     struct interface *ifp;
  1042.     struct mbuf *bp;
  1043. {
  1044.     dump(ifp,IF_TRACE_IN,TRACE_AX25,bp);/* trace the incoming packet */
  1045.     ax_recv(ifp,bp);            /* receive as AX.25 packet */
  1046. }
  1047.  
  1048. /* send raw frame to SCC. used for AX.25 */
  1049. static int
  1050. scc_raw(ifp,bp)
  1051.     struct interface *ifp;
  1052.     struct mbuf *bp;
  1053. {
  1054.     struct sccchan *scc;
  1055.     int i_state;
  1056.  
  1057.     dump(ifp,IF_TRACE_OUT,TRACE_AX25,bp);
  1058.  
  1059.     scc = sccchan[ifp->dev];
  1060.  
  1061.     if (scc->flags & TX_INHIBIT){    /* transmitter inhibit */
  1062.     free_p(bp);
  1063.     return -1;
  1064.     }
  1065.  
  1066.     enqueue(&scc->c.a.sndq,bp);        /* enqueue packet */
  1067.     scc->enqueued++;
  1068.  
  1069.     i_state = disable();
  1070.  
  1071.     if (scc->c.a.tstate == IDLE){    /* when transmitter is idle */
  1072.     scc->c.a.tstate = DEFER;    /* start the key-up sequence */
  1073.     scc->c.a.maxdefer = TPS * scc->c.a.params[IDLETIME] /
  1074.                   scc->c.a.params[SLOTTIME];
  1075.     scc->timercount = scc->c.a.params[WAITTIME];
  1076.     }
  1077.  
  1078.     restore(i_state);
  1079.     return 0;
  1080. }
  1081.  
  1082. /* send raw slip frame to SCC. used for SLIP and KISS */
  1083. static int
  1084. scc_slipraw(ifp,bp)
  1085.     struct interface *ifp;
  1086.     struct mbuf *bp;
  1087. {
  1088.     struct sccchan *scc;
  1089.     register struct slip *sp;
  1090.  
  1091.     scc = sccchan[ifp->dev];
  1092.     sp = &scc->c.s;            /* address SLIP control structure */
  1093.     enqueue(&sp->sndq,bp);        /* enqueue packet (unencoded) */
  1094.     scc->enqueued++;
  1095.  
  1096.     if (sp->tbp == NULLBUF)
  1097.        scc_sstart(scc);
  1098. }
  1099.  
  1100. /* initialize interface for AX.25 use */
  1101. static int
  1102. scc_ax25(ifp,mode,call)
  1103.     register struct interface *ifp;
  1104.     char *mode;
  1105.     char *call;
  1106.  
  1107. {
  1108.     struct ax25_addr hwaddr;
  1109.     struct ax25_call *axc;
  1110.     int ax_send(),ax_output();
  1111.  
  1112.     if (setcall(&hwaddr,call) < 0){
  1113.     printf("Interface %s needs a callsign in %s mode\n",ifp->name,mode);
  1114.     return -1;
  1115.     }
  1116.  
  1117.     axarp();                /* init AX.25 ARP */
  1118.  
  1119.     ifp->send = ax_send;
  1120.     ifp->output = ax_output;
  1121.     ifp->flags |= IF_AX25;
  1122.  
  1123.     if ((ifp->hwaddr = malloc(sizeof(struct ax25_addr))) == NULLCHAR ||
  1124.     (axc = cr_axcall(ax25_call,&hwaddr)) == NULLAXCALL){
  1125.     printf(nospace);
  1126.     return -1;
  1127.     }
  1128.  
  1129.     memcpy(ifp->hwaddr,&hwaddr,sizeof(struct ax25_addr));
  1130.     if (axc->interface != NULLIF)
  1131.     axc->flags |= MULTI_IF;
  1132.     axc->interface = ifp;
  1133.     axc->mode = IP_ARP_CON;
  1134.     return 0;
  1135. }
  1136.  
  1137.  
  1138. /* Interrupt handlers for asynchronous modes (kiss, slip) */
  1139. /* Remember that on the Atari, these routines can ONLY be called */
  1140. /* in SUPERVISOR mode! */
  1141.  
  1142. /* Transmitter interrupt handler */
  1143. /* This routine sends data from mbufs in SLIP format */
  1144. static void
  1145. scc_asytx(scc)
  1146.     register struct sccchan *scc;
  1147.  
  1148. {
  1149.     register struct mbuf *bp;
  1150.  
  1151.     scc->txints++;
  1152.  
  1153.     if (scc->txchar != 0){        /* a character pending for transmit? */
  1154.     WRREG(scc->data,scc->txchar);    /* send it now */
  1155.     scc->txchar = 0;        /* next time, ignore it */
  1156.     return;
  1157.     }
  1158.  
  1159.     if (scc->c.s.tbp == NULLBUF){    /* nothing to send? */
  1160.     if ((scc->c.s.tbp = scc->c.s.sndq) != NULLBUF){ /* dequeue next frame */
  1161.         scc->c.s.sndq = scc->c.s.sndq->anext;
  1162.         WRREG(scc->data,FR_END);    /* send FR_END to flush line garbage */
  1163.     } else {
  1164.         WRREG(scc->ctrl,RES_Tx_P);    /* else only reset pending int */
  1165.     }
  1166.     return;
  1167.     }
  1168.  
  1169.     while ((bp = scc->c.s.tbp)->cnt == 0){ /* nothing left in this mbuf? */
  1170.     bp = bp->next;            /* save link to next */
  1171.     scc->c.s.tbp->next = sys_txfree;/* move this mbuf to txfree list */
  1172.     sys_txfree = scc->c.s.tbp;
  1173.  
  1174.     if ((scc->c.s.tbp = bp) == NULLBUF){ /* see if more mbufs follow */
  1175.         WRREG(scc->data,FR_END);    /* frame complete, send FR_END */
  1176.         return;
  1177.     }
  1178.     }
  1179.     /* now bp = scc->c.s.tbp (either from while or from if stmt above) */
  1180.  
  1181.     switch (uchar(*(bp->data)))        /* next data byte to transmit */
  1182.     {
  1183.     case FR_END:
  1184.     scc->txchar = T_FR_END;        /* next time, send transposed FR_END */
  1185.     WRREG(scc->data,FR_ESC);    /* now, send a FR_ESC */
  1186.     break;
  1187.  
  1188.     case FR_ESC:
  1189.     scc->txchar = T_FR_ESC;        /* next time, send transposed FR_ESC */
  1190.  
  1191.     default:
  1192.     WRREG(scc->data,*(bp->data));    /* just send the character */
  1193.     break;
  1194.     }
  1195.  
  1196.     bp->cnt--;                /* decrease mbuf byte count */
  1197.     bp->data++;                /* and increment the data pointer */
  1198. }
  1199.  
  1200. /* External/Status interrupt handler */
  1201. static void
  1202. scc_asyex(scc)
  1203.     register struct sccchan *scc;
  1204.  
  1205. {
  1206.     register unsigned char status,changes;
  1207.  
  1208.     scc->exints++;
  1209.     status = RDREG(scc->ctrl);
  1210.     changes = status ^ scc->status;
  1211.  
  1212.     if (changes & BRK_ABRT){        /* BREAK? */
  1213.     scc->c.s.errors++;        /* treat as an error to discard frame */
  1214.  
  1215.     if ((status & BRK_ABRT) == 0)    /* BREAK now over? */
  1216.         VOID(RDREG(scc->data));    /* read the NUL character */
  1217.     }
  1218.  
  1219.     scc->status = status;
  1220.     WRREG(scc->ctrl,RES_EXT_INT);
  1221. }
  1222.  
  1223. /* Receiver interrupt handler */
  1224. static void
  1225. scc_asyrx(scc)
  1226.     register struct sccchan *scc;
  1227.  
  1228. {
  1229.     register unsigned char ch;
  1230.     register struct mbuf *bp;
  1231.  
  1232.     scc->rxints++;
  1233.  
  1234.     if (scc->c.s.escaped){
  1235.     /* Translate 2-char escape sequence back to original char */
  1236.     scc->c.s.escaped = 0;
  1237.  
  1238.     switch (ch = RDREG(scc->data))
  1239.     {
  1240.     case T_FR_ESC:
  1241.         ch = FR_ESC;
  1242.         break;
  1243.  
  1244.     case T_FR_END:
  1245.         ch = FR_END;
  1246.         break;
  1247.  
  1248.     case FR_END:            /* escaped FR_END, assume an error */
  1249.         goto discard;
  1250.  
  1251.     default:
  1252.         scc->c.s.errors++;
  1253.         break;
  1254.     }
  1255.     } else {
  1256.     switch (ch = RDREG(scc->data))
  1257.     {
  1258.     case FR_ESC:
  1259.         scc->c.s.escaped = 1;
  1260.         return;
  1261.  
  1262.     case FR_END:
  1263.         if (scc->c.s.rbp != NULLBUF){
  1264.         if (scc->c.s.errors == 0){
  1265.             if (scc->rqueue == NULLBUF){    /* enqueue it */
  1266.             scc->rqueue = scc->c.s.rbp;
  1267.             } else {
  1268.             for (bp = scc->rqueue; bp->anext != NULLBUF; bp = bp->anext)
  1269.                 ;
  1270.             bp->anext = scc->c.s.rbp;
  1271.             }                    /* like enqueue() does */
  1272.  
  1273.             scc->c.s.rbp = scc->c.s.rbp1 = NULLBUF;
  1274.             scc->rxframes++;
  1275.         } else {
  1276. discard:        /* error in frame, put buffers back on sys_rxbufs queue */
  1277.             while ((bp = scc->c.s.rbp) != NULLBUF){
  1278.             scc->c.s.rbp = bp->next;
  1279.             bp->next = sys_rxbufs;
  1280.             sys_rxbufs = bp;
  1281.             bp->cnt = 0;        /* reset count for next user */
  1282.             cur_rxbufs++;
  1283.             }
  1284.  
  1285.             scc->c.s.rbp1 = NULLBUF;
  1286.             scc->rxerrs++;
  1287.         }
  1288.         }
  1289.         scc->c.s.errors = 0;
  1290.         return;
  1291.  
  1292.     default:            /* a normal char, fall through */
  1293.         break;
  1294.     }
  1295.     }
  1296.     /* now ch holds the next character for the receive buffer */
  1297.  
  1298.     if (scc->c.s.errors)        /* we already have an error in this frame */
  1299.     return;                /* so don't waste time and buffers */
  1300.  
  1301.     if ((bp = scc->c.s.rbp1) == NULLBUF){ /* no buffer available now */
  1302.     if ((bp = sys_rxbufs) == NULLBUF){ /* system out of buffers */
  1303.         if (!scc->c.s.errors)
  1304.         scc->nospace++;        /* count these events (1 per frame) */
  1305.         scc->c.s.errors++;        /* cannot store the character now */
  1306.         return;
  1307.     }
  1308.  
  1309.     sys_rxbufs = bp->next;        /* get the buffer from list */
  1310.     bp->next = NULLBUF;
  1311.     cur_rxbufs--;
  1312.  
  1313.     if (scc->c.s.rbp == NULLBUF){    /* append it to rx list */
  1314.         scc->c.s.rbp = scc->c.s.rbp1 = bp;
  1315.     } else {
  1316.         scc->c.s.rbp1 = bp;
  1317.         for (bp = scc->c.s.rbp; bp->next != NULLBUF; bp = bp->next)
  1318.         ;
  1319.         bp->next = scc->c.s.rbp1;
  1320.         bp = scc->c.s.rbp1;
  1321.     }                /* like append() does */
  1322.     }
  1323.     /* now bp = scc->c.s.rbp1 */
  1324.  
  1325.     bp->data[bp->cnt++] = ch;        /* store the character */
  1326.  
  1327.     if (bp->cnt == bp->size)        /* buffer full? */
  1328.     scc->c.s.rbp1 = NULLBUF;    /* acquire a new one next time */
  1329. }
  1330.  
  1331. /* Receive Special Condition interrupt handler */
  1332. static void
  1333. scc_asysp(scc)
  1334.     register struct sccchan *scc;
  1335.  
  1336. {
  1337.     register unsigned char status;
  1338.  
  1339.     scc->spints++;
  1340.  
  1341.     status = rd(scc,R1);        /* read receiver status */
  1342.     VOID(RDREG(scc->data));        /* flush offending character */
  1343.  
  1344.     if (status & CRC_ERR){        /* did a framing error occur? */
  1345.     scc->c.s.errors++;        /* treat as an error to discard frame */
  1346.     } else {
  1347.     if (status & Rx_OVR){        /* did we get an overrun? */
  1348.         scc->rovers++;        /* count them */
  1349.         scc->c.s.errors++;        /* treat as an error to discard frame */
  1350.     }
  1351.     }
  1352.  
  1353.     WRREG(scc->ctrl,ERR_RES);
  1354. }
  1355.  
  1356.  
  1357. /* Interrupt handlers for sdlc mode (AX.25) */
  1358. /* Remember that on the Atari, these routines can ONLY be called */
  1359. /* in SUPERVISOR mode! */
  1360.  
  1361. /* Transmitter interrupt handler */
  1362. static void
  1363. scc_sdlctx(scc)
  1364.     register struct sccchan *scc;
  1365.  
  1366. {
  1367.     register struct mbuf *bp;
  1368.  
  1369.     scc->txints++;
  1370.  
  1371.     switch (scc->c.a.tstate)        /* look at transmitter state */
  1372.     {
  1373.     case ACTIVE:            /* busy sending data bytes */
  1374.     while ((bp = scc->c.a.tbp)->cnt == 0){    /* nothing left in this mbuf? */
  1375.         bp = bp->next;            /* save link to next */
  1376.         scc->c.a.tbp->next = sys_txfree;    /* move this mbuf to txfree list */
  1377.         sys_txfree = scc->c.a.tbp;
  1378.  
  1379.         if ((scc->c.a.tbp = bp) == NULLBUF){/* see if more mbufs follow */
  1380.         if (RDREG(scc->ctrl) & TxEOM){    /* check tx underrun status */
  1381.             scc->rovers++;        /* oops, an underrun! count them */
  1382.             WRREG(scc->ctrl,SEND_ABORT);/* send an abort to be sure */
  1383.             scc->c.a.tstate = TAIL;    /* key down tx after TAILTIME */
  1384.             scc->timercount = scc->c.a.params[TAILTIME];
  1385.             return;
  1386.         }
  1387.  
  1388.         cl(scc,R10,ABUNDER);        /* frame complete, allow CRC transmit */
  1389.         scc->c.a.tstate = FLUSH;
  1390.         WRREG(scc->ctrl,RES_Tx_P);    /* reset pending int */
  1391.         return;
  1392.         }
  1393.     }
  1394.     /* now bp = scc->c.a.tbp (either from while or from if stmt above) */
  1395.  
  1396.     WRREG(scc->data,*(bp->data++)); /* send the character */
  1397.     bp->cnt--;            /* decrease mbuf byte count */
  1398.     return;
  1399.  
  1400.     case FLUSH:                /* CRC just went out, more to send? */
  1401.     or(scc,R10,ABUNDER);        /* re-install underrun protection */
  1402.     /* verify that we are not exeeding max tx time (if defined) */
  1403.     if ((scc->timercount != 0 || scc->c.a.params[MAXKEYUP] == 0) &&
  1404.         (scc->c.a.tbp = scc->c.a.sndq) != NULLBUF){ /* dequeue a frame */
  1405.         scc->c.a.sndq = scc->c.a.sndq->anext;
  1406.         WRREG(scc->ctrl,RES_Tx_CRC); /* reset the TX CRC generator */
  1407.         scc->c.a.tstate = ACTIVE;
  1408.         scc_sdlctx(scc);        /* write 1st byte */
  1409.         WRREG(scc->ctrl,RES_EOM_L); /* reset the EOM latch */
  1410.         return;
  1411.     }
  1412.  
  1413.     scc->c.a.tstate = TAIL;        /* no more, key down tx after TAILTIME */
  1414.     scc->timercount = scc->c.a.params[TAILTIME];
  1415.     WRREG(scc->ctrl,RES_Tx_P);
  1416.     return;
  1417.  
  1418.     default:                /* another state */
  1419.     WRREG(scc->ctrl,RES_Tx_P);    /* then don't send anything */
  1420.     return;
  1421.     }
  1422. }
  1423.  
  1424. /* External/Status interrupt handler */
  1425. static void
  1426. scc_sdlcex(scc)
  1427.     register struct sccchan *scc;
  1428.  
  1429. {
  1430.     register unsigned char status,changes;
  1431.  
  1432.     scc->exints++;
  1433.     status = RDREG(scc->ctrl);
  1434.     changes = status ^ scc->status;
  1435.  
  1436.     if (changes & BRK_ABRT){        /* Received an ABORT */
  1437.     if (status & BRK_ABRT){        /* is this the beginning? */
  1438.         if (scc->c.a.rbp != NULLBUF){/* did we receive something? */
  1439.         /* check if a significant amount of data came in */
  1440.         /* this is because the drop of DCD tends to generate an ABORT */
  1441.         if (scc->c.a.rbp->next != NULLBUF || scc->c.a.rbp->cnt > 10)
  1442.             scc->rxerrs++;    /* then count it as an error */
  1443.         scc_tossb(scc);        /* throw away buffer */
  1444.         }
  1445.         VOID(RDREG(scc->data));    /* flush the FIFO */
  1446.         VOID(RDREG(scc->data));
  1447.         VOID(RDREG(scc->data));
  1448.     }
  1449.     }
  1450.  
  1451.     if (changes & CTS){            /* CTS input changed state */
  1452.     if (status & CTS){        /* CTS is now ON */
  1453.         if (scc->c.a.tstate == KEYWT &&
  1454.         scc->c.a.params[TXDELAY] == 0) /* zero TXDELAY = wait for CTS */
  1455.         scc->timercount = 1;    /* it will start within 10 ms */
  1456.     }
  1457.     }
  1458.  
  1459.     if (changes & DCD){            /* DCD input changed state */
  1460.     if (status & DCD){        /* DCD is now ON */
  1461.         if (!(scc->flags & EXTCLOCK))
  1462.         WRSCC(scc->ctrl,R14,SEARCH|scc->wreg[R14]); /* DPLL: enter search mode */
  1463.         or(scc,R3,ENT_HM|RxENABLE); /* enable the receiver, hunt mode */
  1464.     } else {            /* DCD is now OFF */
  1465.         cl(scc,R3,ENT_HM|RxENABLE); /* disable the receiver */
  1466.         VOID(RDREG(scc->data));    /* flush the FIFO */
  1467.         VOID(RDREG(scc->data));
  1468.         VOID(RDREG(scc->data));
  1469.         if (scc->c.a.rbp != NULLBUF){/* did we receive something? */
  1470.         /* check if a significant amount of data came in */
  1471.         /* this is because some characters precede the drop of DCD */
  1472.         if (scc->c.a.rbp->next != NULLBUF || scc->c.a.rbp->cnt > 10)
  1473.             scc->rxerrs++;    /* then count it as an error */
  1474.         scc_tossb(scc);        /* throw away buffer */
  1475.         }
  1476.     }
  1477.     }
  1478.  
  1479.     scc->status = status;
  1480.     WRREG(scc->ctrl,RES_EXT_INT);
  1481. }
  1482.  
  1483. /* Receiver interrupt handler */
  1484. static void
  1485. scc_sdlcrx(scc)
  1486.     register struct sccchan *scc;
  1487.  
  1488. {
  1489.     register struct mbuf *bp;
  1490.  
  1491.     scc->rxints++;
  1492.  
  1493.     if ((bp = scc->c.a.rbp1) == NULLBUF){ /* no buffer available now */
  1494.     if ((bp = sys_rxbufs) == NULLBUF){ /* system out of buffers */
  1495.         VOID(RDREG(scc->data));    /* so we have to discard the char */
  1496.         or(scc,R3,ENT_HM);        /* enter hunt mode for next flag */
  1497.         scc_tossb(scc);        /* put buffers back on pool */
  1498.         scc->nospace++;        /* count these events */
  1499.         return;
  1500.     }
  1501.  
  1502.     sys_rxbufs = bp->next;        /* get the buffer from list */
  1503.     bp->next = NULLBUF;
  1504.     cur_rxbufs--;
  1505.  
  1506.     if (scc->c.a.rbp == NULLBUF){    /* append it to rx list */
  1507.         scc->c.a.rbp = scc->c.a.rbp1 = bp;
  1508.     } else {
  1509.         scc->c.a.rbp1 = bp;
  1510.         for (bp = scc->c.a.rbp; bp->next != NULLBUF; bp = bp->next)
  1511.         ;
  1512.         bp->next = scc->c.a.rbp1;
  1513.         bp = scc->c.a.rbp1;
  1514.     }                /* like append() does */
  1515.     }
  1516.  
  1517.     /* now, we have a buffer (at bp). read character and store it */
  1518.  
  1519.     bp->data[bp->cnt++] = RDREG(scc->data);
  1520.  
  1521.     if (bp->cnt == bp->size)        /* buffer full? */
  1522.     scc->c.a.rbp1 = NULLBUF;    /* acquire a new one next time */
  1523. }
  1524.  
  1525. /* Receive Special Condition interrupt handler */
  1526. static void
  1527. scc_sdlcsp(scc)
  1528.     register struct sccchan *scc;
  1529.  
  1530. {
  1531.     register unsigned char status;
  1532.     register struct mbuf *bp;
  1533.  
  1534.     scc->spints++;
  1535.  
  1536.     status = rd(scc,R1);        /* read receiver status */
  1537.     VOID(RDREG(scc->data));        /* flush offending character */
  1538.  
  1539.     if (status & Rx_OVR){        /* receiver overrun */
  1540.     scc->rovers++;            /* count them */
  1541.     or(scc,R3,ENT_HM);        /* enter hunt mode for next flag */
  1542.     scc_tossb(scc);            /* put buffers back on pool */
  1543.     }
  1544.  
  1545.     if (status & END_FR &&        /* end of frame */
  1546.     scc->c.a.rbp != NULLBUF){    /* at least received something */
  1547.     if ((status & CRC_ERR) == 0 &&    /* no CRC error is indicated */
  1548.         (status & 0xe) == RES8){    /* 8 bits in last byte */
  1549.  
  1550.         /* we seem to have a good frame. but the last byte received */
  1551.         /* from rx interrupt is in fact a CRC byte, so discard it */
  1552.         if (scc->c.a.rbp1 != NULLBUF){
  1553.         scc->c.a.rbp1->cnt--;    /* current mbuf was not full */
  1554.         } else {
  1555.         for (bp = scc->c.a.rbp; bp->next != NULLBUF; bp = bp->next)
  1556.             ;            /* find last mbuf */
  1557.  
  1558.         bp->cnt--;        /* last byte is first CRC byte */
  1559.         }
  1560.  
  1561.         if (scc->rqueue == NULLBUF){/* enqueue it */
  1562.         scc->rqueue = scc->c.a.rbp;
  1563.         } else {
  1564.         for (bp = scc->rqueue; bp->anext != NULLBUF; bp = bp->anext)
  1565.             ;
  1566.         bp->anext = scc->c.a.rbp;
  1567.         }                /* like enqueue() does */
  1568.  
  1569.         scc->c.a.rbp = scc->c.a.rbp1 = NULLBUF;
  1570.         scc->rxframes++;
  1571.     } else {            /* a bad frame */
  1572.         scc_tossb(scc);        /* throw away frame */
  1573.         scc->rxerrs++;
  1574.     }
  1575.     }
  1576.  
  1577.     WRREG(scc->ctrl,ERR_RES);
  1578. }
  1579.  
  1580. /* Throw away receive mbuf(s) when an error occurred */
  1581. static void
  1582. scc_tossb (scc)
  1583.     register struct sccchan *scc;
  1584.  
  1585. {
  1586.     register struct mbuf *bp;
  1587.  
  1588.     if (scc->c.a.rbp != NULLBUF){
  1589.     /* move all buffers back to the sys_rxbufs list */
  1590.     while ((bp = scc->c.a.rbp) != NULLBUF){
  1591.         scc->c.a.rbp = bp->next;
  1592.         bp->next = sys_rxbufs;
  1593.         sys_rxbufs = bp;
  1594.         bp->cnt = 0;        /* reset count for next user */
  1595.         cur_rxbufs++;
  1596.     }
  1597.  
  1598.     scc->c.a.rbp1 = NULLBUF;
  1599.     }
  1600. }
  1601.  
  1602. /* Switch the SCC to "transmit" mode */
  1603. /* Only to be called from an interrupt handler, while in AX.25 mode */
  1604. static void
  1605. scc_txon(scc)
  1606.     register struct sccchan *scc;
  1607. {
  1608.     if (!(scc->flags & (DIVIDER|EXTCLOCK))){ /* halfduplex without divider? */
  1609.     cl(scc,R3,RxENABLE);        /* then switch off receiver */
  1610.     cl(scc,R5,TxENAB);        /* transmitter off during switch */
  1611.     scc_speed(scc,1,scc->speed);    /* reprogram baudrate generator */
  1612.     }
  1613.  
  1614.     or(scc,R5,RTS|TxENAB);        /* set the RTS line and enable TX */
  1615.  
  1616. #ifdef MSDOS
  1617.     if (sccinfo.hwtype & PRIMUS)    /* PRIMUS has another PTT bit... */
  1618.     WRREG(scc->ctrl + 4,sccinfo.hwparam | 0x80); /* set that bit! */
  1619. #endif
  1620. }
  1621.  
  1622. /* Switch the SCC to "receive" mode (or: switch off transmitter) */
  1623. /* Only to be called from an interrupt handler, while in AX.25 mode */
  1624. static void
  1625. scc_txoff(scc)
  1626.     register struct sccchan *scc;
  1627. {
  1628.     cl(scc,R5,RTS);            /* turn off RTS line */
  1629.  
  1630. #ifdef MSDOS
  1631.     if (sccinfo.hwtype & PRIMUS)    /* PRIMUS has another PTT bit... */
  1632.     WRREG(scc->ctrl + 4,sccinfo.hwparam); /* clear that bit! */
  1633. #endif
  1634.  
  1635.     if (!(scc->flags & (DIVIDER|EXTCLOCK))){ /* halfduplex without divider? */
  1636.     cl(scc,R5,TxENAB);        /* then disable the transmitter */
  1637.     scc_speed(scc,32,scc->speed);    /* back to receiver baudrate */
  1638.     }
  1639. }
  1640.  
  1641. /* SCC timer interrupt handler. Will be called every 1/TPS s by the system */
  1642. /* timer interrupt.  The usual timer library is not used because it will */
  1643. /* only fire handlers from the main program loop. This is much too slow. */
  1644.  
  1645. void scctim()
  1646.  
  1647. {
  1648.     register struct sccchan *scc;
  1649.     register struct sccchan **sccp;
  1650.  
  1651. #ifdef MSDOS
  1652.     sccinfo.ticks++;            /* keep track of number of ticks */
  1653. #endif
  1654.  
  1655.     for (sccp = sccchan + sccinfo.maxchan; sccp >= sccchan; sccp--){
  1656.     if ((scc = *sccp) != NULLCHAN &&
  1657.         scc->timercount != 0 &&
  1658.         --(scc->timercount) == 0){
  1659.         /* handle an SCC timer event for this SCC channel */
  1660.         /* this can only happen when the channel is AX.25 type */
  1661.         /* (the SLIP/KISS driver does not use timers) */
  1662.  
  1663.         switch (scc->c.a.tstate)
  1664.         {
  1665.         case IDLE:            /* it was idle, this is FULLDUP2 timeout */
  1666.         scc_txoff(scc);        /* switch-off the transmitter */
  1667.         break;
  1668.  
  1669.         case DEFER:            /* trying to get the channel */
  1670.         /* operation is as follows:
  1671.          * CSMA: when channel clear AND persistence randomgenerator
  1672.          *     wins, AND group restrictions allow it:
  1673.          *        keyup the transmitter
  1674.          *     if not, delay one SLOTTIME and try again
  1675.          * FULL: always keyup the transmitter
  1676.          */
  1677.         if (scc->c.a.params[FULLDUP] == 0){
  1678.             random = 21 * random + 53;
  1679.  
  1680.             if (scc->status & DCD || scc->c.a.params[PERSIST] < random){
  1681.             /* defer transmission again. check for limit */
  1682. defer_it:        if (--(scc->c.a.maxdefer) == 0){
  1683.                 /* deferred too long. choice is to:
  1684.                  * - throw away pending frames, or
  1685.                  * - smash-on the transmitter and send them.
  1686.                  * the first would be the choice in a clean
  1687.                  * environment, but in the amateur radio world
  1688.                  * a distant faulty station could tie us up
  1689.                  * forever, so the second may be better...
  1690.                  */
  1691. #ifdef THROW_AWAY_AFTER_DEFER_TIMEOUT
  1692.                 struct mbuf *bp,*bp1;
  1693.  
  1694.                 while ((bp = scc->c.a.sndq) != NULLBUF){
  1695.                 scc->c.a.sndq = scc->c.a.sndq->anext;
  1696.                 /* move this mbuf chain to the txfree list */
  1697.                 for (bp1 = bp; bp1->next != NULLBUF; bp1 = bp1->next)
  1698.                     ;
  1699.                 bp1->next = sys_txfree;
  1700.                 sys_txfree = bp;
  1701.                 }
  1702. #else
  1703.                 goto keyup; /* just keyup the transmitter... */
  1704. #endif
  1705.             }
  1706.  
  1707.             scc->timercount = scc->c.a.params[SLOTTIME];
  1708.             break;
  1709.             }
  1710.  
  1711.             if (uchar(scc->group) != NOGROUP)
  1712.             {
  1713.             int i;
  1714.             struct sccchan *scc2;
  1715.  
  1716.             for (i = 0; i <= sccinfo.maxchan; i++)
  1717.                 if ((scc2 = sccchan[i]) != NULLCHAN &&
  1718.                 scc2 != scc &&
  1719.                 uchar(scc2->group) & uchar(scc->group) &&
  1720.                 ((scc->group & TXGROUP && scc2->wreg[R5] & RTS) ||
  1721.                  (scc->group & RXGROUP && scc2->status & DCD))){
  1722.                 goto defer_it;
  1723.             }
  1724.             }
  1725.         }
  1726.  
  1727.         case KEYUP:            /* keyup transmitter (note fallthrough) */
  1728. keyup:        if ((scc->wreg[R5] & RTS) == 0){ /* when not yet keyed */
  1729.             scc->c.a.tstate = KEYWT;
  1730.             scc->timercount = scc->c.a.params[TXDELAY]; /* 0 if CTSwait */
  1731.             scc_txon(scc);
  1732.             break;
  1733.         }
  1734.         /* when already keyed, directly fall through */
  1735.  
  1736.         case KEYWT:            /* waited for CTS or TXDELAY */
  1737.         /* when a frame is available (it should be...):
  1738.          * - dequeue it from the send queue
  1739.          * - reset the transmitter CRC generator
  1740.          * - set a timeout on transmission length, if defined
  1741.          * - send the first byte of the frame
  1742.          * - reset the EOM latch
  1743.          * when no frame available, proceed to TAIL handling
  1744.          */
  1745.         if ((scc->c.a.tbp = scc->c.a.sndq) != NULLBUF){
  1746.             scc->c.a.sndq = scc->c.a.sndq->anext;
  1747.             WRREG(scc->ctrl,RES_Tx_CRC);
  1748.             scc->c.a.tstate = ACTIVE;
  1749.             scc->timercount = TPS * scc->c.a.params[MAXKEYUP];
  1750.             scc_sdlctx(scc);
  1751.             WRREG(scc->ctrl,RES_EOM_L);
  1752.             break;
  1753.         }
  1754.         /* when no frame queued, fall through to TAIL case */
  1755.  
  1756.         case TAIL:            /* at end of frame */
  1757.         /* when fulldup is 0 or 1, switch off the transmitter.
  1758.          * when frames are still queued (because of transmit time limit),
  1759.          * restart the procedure to get the channel after MINTIME.
  1760.          * when fulldup is 2, the transmitter remains keyed and we
  1761.          * continue sending.    IDLETIME is an idle timeout in this case.
  1762.          */
  1763.         if (scc->c.a.params[FULLDUP] < 2){
  1764.             scc->c.a.tstate = IDLE;
  1765.             scc_txoff(scc);
  1766.  
  1767.             if (scc->c.a.sndq != NULLBUF){
  1768.             scc->c.a.tstate = DEFER;
  1769.             scc->c.a.maxdefer = TPS * scc->c.a.params[IDLETIME] /
  1770.                           scc->c.a.params[SLOTTIME];
  1771.             scc->timercount = TPS * scc->c.a.params[MINTIME];
  1772.             }
  1773.             break;
  1774.         }
  1775.  
  1776.         if (scc->c.a.sndq != NULLBUF){ /* still frames on the queue? */
  1777.             scc->c.a.tstate = KEYWT; /* continue sending */
  1778.             scc->timercount = TPS * scc->c.a.params[MINTIME]; /* after mintime */
  1779.         } else {
  1780.             scc->c.a.tstate = IDLE;
  1781.             scc->timercount = TPS * scc->c.a.params[IDLETIME];
  1782.         }
  1783.         break;
  1784.  
  1785.         case ACTIVE:        /* max keyup time expired */
  1786.         case FLUSH:            /* same while in flush mode */
  1787.         break;            /* no action required yet */
  1788.  
  1789.         default:            /* unexpected state */
  1790.         scc->c.a.tstate = IDLE; /* that should not happen, but... */
  1791.         scc_txoff(scc);        /* at least stop the transmitter */
  1792.         break;
  1793.         }
  1794.     }
  1795.     }
  1796. }
  1797.